package com.org.web.support.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.time.Duration;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * @author 作者 孝义单:
 * @version 创建时间：2018/5/5 15:31 类说明
 */
@EnableCaching
@Configuration
public class RedisCacheConfig {

  @Value("${spring.cache.expire-time-seconds}")
  public long CacheExpireTimeOfSeconds = 300;

  /**
   * 设置 redis 数据默认过期时间 设置@cacheable 序列化方式
   */
  @Bean
  public RedisCacheConfiguration redisCacheConfiguration() {
    Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(
        Object.class);
    ObjectMapper om = new ObjectMapper();
    om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    jackson2JsonRedisSerializer.setObjectMapper(om);
    RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
    configuration = configuration.serializeValuesWith(
        RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
        .entryTtl(Duration.ofSeconds(CacheExpireTimeOfSeconds));
    configuration.entryTtl(Duration.ofSeconds(CacheExpireTimeOfSeconds));
    return configuration;
  }

  @Bean
  public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
    RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();
    redisTemplate.setConnectionFactory(factory);
    //key序列化方式;（不然会出现乱码;）,但是如果方法上有Long等非String类型的话，会报类型转换错误；
    //所以在没有自己定义key生成策略的时候，以下这个代码建议不要这么写，可以不配置或者自己实现ObjectRedisSerializer
    //或者JdkSerializationRedisSerializer序列化方式;
    RedisSerializer<String> redisSerializer = new StringRedisSerializer();//Long类型不可以会出现异常信息;
    redisTemplate.setKeySerializer(redisSerializer);
    redisTemplate.setHashKeySerializer(redisSerializer);
    return redisTemplate;
  }

 /* @Bean
  public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
    RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
        .entryTtl(Duration.ofSeconds(CacheExpireTimeOfSeconds)); // 设置缓存有效期一小时
    return RedisCacheManager
        .builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
        .cacheDefaults(redisCacheConfiguration).build();
  }*/

  /*@Bean
  public CacheManager cacheManager(RedisConnectionFactory factory) {
    RedisCacheConfiguration config = RedisCacheConfiguration
        .defaultCacheConfig();  // 生成一个默认配置，通过config对象即可对缓存进行自定义配置
    config = config.entryTtl(Duration.ofSeconds(CacheExpireTimeOfSeconds))  // 设置缓存的默认过期时间，也是使用Duration设置
        .disableCachingNullValues();   // 不缓存空值
    // 设置一个初始化的缓存空间set集合
    Set<String> cacheNames = new HashSet<>();
    cacheNames.add("my-redis-cache1");
    cacheNames.add("my-redis-cache2");
    // 对每个缓存空间应用不同的配置
    Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
    configMap.put("my-redis-cache1", config);
    configMap.put("my-redis-cache2", config.entryTtl(Duration.ofSeconds(120)));
    RedisCacheManager cacheManager = RedisCacheManager
        .builder(factory)     // 使用自定义的缓存配置初始化一个cacheManager
        .initialCacheNames(cacheNames)  // 注意这两句的调用顺序，一定要先调用该方法设置初始化的缓存名，再初始化相关的配置
        .withInitialCacheConfigurations(configMap)
        .build();
    return cacheManager;
  }*/

}
